bitkeeper revision 1.1159.38.3 (4123550cLBAC07otAj8ftsT6MzujHQ)
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Wed, 18 Aug 2004 13:09:32 +0000 (13:09 +0000)
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>
Wed, 18 Aug 2004 13:09:32 +0000 (13:09 +0000)
Make backend domain a per-device parameter.
Restructure device controllers and adjust
config handling.

tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xend/server/SrvDaemon.py
tools/python/xen/xend/server/blkif.py
tools/python/xen/xend/server/controller.py
tools/python/xen/xend/server/netif.py
tools/python/xen/xm/create.py

index d2bff39b04a3adca33a1cea5b4f3a06144add179..63dc7f49ab08b470e01d32bf927c3352d9b2360b 100644 (file)
@@ -137,7 +137,7 @@ def lookup_disk_uname(uname):
         segments = None
     return segments
 
-def make_disk(vm, uname, dev, mode, recreate=0):
+def make_disk(vm, config, uname, dev, mode, recreate=0):
     """Create a virtual disk device for a domain.
 
     @param vm:       vm
@@ -154,13 +154,8 @@ def make_disk(vm, uname, dev, mode, recreate=0):
         raise VmError("vbd: Multi-segment vdisk: uname=%s" % uname)
     segment = segments[0]
     vdev = blkdev_name_to_number(dev)
-    backend = vm.get_device_backend('vbd')
-    ctrl = xend.blkif_create(vm.dom, recreate=recreate, backend=backend)
-    
-    def fn(ctrl):
-        return xend.blkif_dev_create(vm.dom, vdev, mode, segment, recreate=recreate)
-    ctrl.addCallback(fn)
-    return ctrl
+    ctrl = xend.blkif_create(vm.dom, recreate=recreate)
+    return ctrl.attachDevice(config, vdev, mode, segment, recreate=recreate)
         
 def vif_up(iplist):
     """send an unsolicited ARP reply for all non link-local IP addresses.
@@ -340,22 +335,6 @@ def append_deferred(dlist, v):
     if isinstance(v, defer.Deferred):
         dlist.append(v)
 
-def _vm_configure1(val, vm):
-    d = vm.create_devices()
-    d.addCallback(_vm_configure2, vm)
-    return d
-
-def _vm_configure2(val, vm):
-    d = vm.configure_fields()
-    def cbok(results):
-        return vm
-    def cberr(err):
-        vm.destroy()
-        return err
-    d.addCallback(cbok)
-    d.addErrback(cberr)
-    return d
-
 class XendDomainInfo:
     """Virtual machine object."""
 
@@ -379,7 +358,6 @@ class XendDomainInfo:
         self.console = None
         self.devices = {}
         self.device_index = {}
-        self.device_backends = {}
         self.configs = []
         self.info = None
         self.ipaddrs = []
@@ -675,7 +653,6 @@ class XendDomainInfo:
         
         self.devices = {}
         self.device_index = {}
-        self.device_backends = {}
         self.configs = []
         self.ipaddrs = []
 
@@ -915,25 +892,6 @@ class XendDomainInfo:
             self.restart_state = None
         return d
 
-    def configure_device_backend(self, type, sxpr):
-        """Configure the backend domain to use for devices of a given type.
-
-        @param type: device type
-        @param sxpr: config
-        @raise: VmError if the domain id is missing
-        @raise: VmError if the domain does not exist
-        """
-        dom = sxp.child_value(sxpr, 'domain')
-        if dom is None:
-            raise VmError('missing backend domain')
-        dominfo = domain_exists(dom)
-        if dominfo is None:
-            raise VmError('invalid backend domain:' + dom)
-        self.device_backends[type] = dominfo.dom
-
-    def get_device_backend(self, type):
-        return self.device_backends.get(type, 0)
-
     def configure_backends(self):
         """Set configuration flags if the vm is a backend for netif or blkif.
         Configure the backends to use for vbd and vif if specified.
@@ -945,21 +903,9 @@ class XendDomainInfo:
                 self.blkif_backend = 1
             elif name == 'netif':
                 self.netif_backend = 1
-            elif name == 'vbd':
-                self.configure_device_backend('vbd', v)
-            elif name == 'vif':
-                self.configure_device_backend('vif', v)
             else:
                 raise VmError('invalid backend type:' + str(name))
 
-    def create_backends(self):
-        """Setup the netif and blkif backends.
-        """
-        if self.blkif_backend:
-            xend.blkif_set_control_domain(self.dom, recreate=self.recreate)
-        if self.netif_backend:
-            xend.netif_set_control_domain(self.dom, recreate=self.recreate)
-            
     def configure(self):
         """Configure a vm.
 
@@ -968,12 +914,19 @@ class XendDomainInfo:
 
         returns Deferred - calls callback with vm
         """
-        if self.blkif_backend:
-            d = defer.Deferred()
-            d.callback(self)
-        else:
-            d = xend.blkif_create(self.dom, recreate=self.recreate)
-        d.addCallback(_vm_configure1, self)
+        d = self.create_devices()
+        d.addCallback(self._configure)
+        return d
+
+    def _configure(self, val):
+        d = self.configure_fields()
+        def cbok(results):
+            return self
+        def cberr(err):
+            self.destroy()
+            return err
+        d.addCallback(cbok)
+        d.addErrback(cberr)
         return d
 
     def dom_construct(self, dom, config):
@@ -1078,16 +1031,14 @@ def vm_dev_vif(vm, val, index):
     #    raise VmError('vif: vif in netif backend domain')
     vif = vm.next_device_index('vif')
     vmac = sxp.child_value(val, "mac")
-    backend = vm.get_device_backend('vif')
-    xend.netif_create(vm.dom, recreate=vm.recreate, backend=backend)
+    ctrl = xend.netif_create(vm.dom, recreate=vm.recreate)
     log.debug("Creating vif dom=%d vif=%d mac=%s", vm.dom, vif, str(vmac))
-    defer = xend.netif_dev_create(vm.dom, vif, val, recreate=vm.recreate)
-    def fn(id):
-        dev = xend.netif_dev(vm.dom, vif)
+    defer = ctrl.attachDevice(vif, val, recreate=vm.recreate)
+    def cbok(dev):
         dev.vifctl('up', vmname=vm.name)
         vm.add_device('vif', dev)
-        return id
-    defer.addCallback(fn)
+        return dev
+    defer.addCallback(cbok)
     return defer
 
 def vm_dev_vbd(vm, val, index):
@@ -1108,7 +1059,7 @@ def vm_dev_vbd(vm, val, index):
         raise VmError('vbd: Missing dev')
     mode = sxp.child_value(val, 'mode', 'r')
     log.debug("Creating vbd dom=%d uname=%s dev=%s", vm.dom, uname, dev)
-    defer = make_disk(vm, uname, dev, mode, vm.recreate)
+    defer = make_disk(vm, val, uname, dev, mode, vm.recreate)
     def fn(vbd):
         vbd.dev = dev
         vbd.uname = uname
index e6a1f309008e462aa44996475cefcfd8ef741c2f..2cf58db57af402ff1d23a0f09d835da60c7b884b 100644 (file)
@@ -651,23 +651,12 @@ class Daemon:
         """
         return self.channelF.getDomChannel(dom)
 
-    def blkif_set_control_domain(self, dom, recreate=0):
-        """Set the block device backend control domain.
-        """
-        return self.blkifCF.setControlDomain(dom, recreate=recreate)
-    
-    def blkif_get_control_domain(self, dom):
-        """Get the block device backend control domain.
-        """
-        return self.blkifCF.getControlDomain()
-    
-    def blkif_create(self, dom, recreate=0, backend=0):
+    def blkif_create(self, dom, recreate=0):
         """Create a block device interface controller.
         
-        Returns Deferred
+        Returns controller
         """
-        d = self.blkifCF.createInstance(dom, recreate=recreate, backend=backend)
-        return d
+        return self.blkifCF.createInstance(dom, recreate=recreate)
 
     def blkifs(self):
         return [ x.sxpr() for x in self.blkifCF.getInstances() ]
@@ -678,7 +667,7 @@ class Daemon:
     def blkif_dev(self, dom, vdev):
         return self.blkifCF.getDomainDevice(dom, vdev)
 
-    def blkif_dev_create(self, dom, vdev, mode, segment, recreate=0):
+    def blkif_dev_create(self, dom, config, vdev, mode, segment, recreate=0):
         """Create a block device.
         
         Returns Deferred
@@ -686,24 +675,14 @@ class Daemon:
         ctrl = self.blkifCF.getInstanceByDom(dom)
         if not ctrl:
             raise XendError('No blkif controller: %d' % dom)
-        d = ctrl.attachDevice(vdev, mode, segment, recreate=recreate)
+        d = ctrl.attachDevice(config, vdev, mode, segment, recreate=recreate)
         return d
 
-    def netif_set_control_domain(self, dom, recreate=0):
-        """Set the network interface backend control domain.
-        """
-        return self.netifCF.setControlDomain(dom, recreate=recreate)
-
-    def netif_get_control_domain(self, dom):
-        """Get the network interface backend control domain.
-        """
-        return self.netifCF.getControlDomain()
-    
-    def netif_create(self, dom, recreate=0, backend=0):
+    def netif_create(self, dom, recreate=0):
         """Create a network interface controller.
         
         """
-        return self.netifCF.createInstance(dom, recreate=recreate, backend=backend)
+        return self.netifCF.createInstance(dom, recreate=recreate)
 
     def netifs(self):
         return [ x.sxpr() for x in self.netifCF.getInstances() ]
index c142e59da86d3e0c84aa48b19333200e39f2a218..4a683610cb0d99d406aed276ce36d774348e43c6 100755 (executable)
@@ -17,13 +17,19 @@ class BlkifBackendController(controller.BackendController):
     """ Handler for the 'back-end' channel to a device driver domain.
     """
 
-    def __init__(self, factory, dom):
-        controller.BackendController.__init__(self, factory, dom)
+    def __init__(self, ctrl, dom, handle):
+        controller.BackendController.__init__(self, ctrl, dom, handle)
+        self.connected = 0
+        self.evtchn = None
+        self.handle = handle
         self.addMethod(CMSG_BLKIF_BE,
                        CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED,
                        self.recv_be_driver_status_changed)
         self.registerChannel()
 
+    def __str__(self):
+        return '<BlkifBackendController %d %d>' % (self.controller.dom, self.dom)
+
     def recv_be_driver_status_changed(self, msg, req):
         """Request handler for be_driver_status_changed messages.
         
@@ -35,32 +41,109 @@ class BlkifBackendController(controller.BackendController):
         val = unpackMsg('blkif_be_driver_status_changed_t', msg)
         status = val['status']
 
-class BlkifControllerFactory(controller.SplitControllerFactory):
+    def connect(self, recreate=0):
+        """Connect the controller to the blkif control interface.
+
+        @param recreate: true if after xend restart
+        @return: deferred
+        """
+        log.debug("Connecting blkif %s", str(self))
+        if recreate or self.connected:
+            d = defer.succeed(self)
+        else:
+            d = self.send_be_create()
+            d.addCallback(self.respond_be_create)
+        return d
+        
+    def send_be_create(self):
+        d = defer.Deferred()
+        msg = packMsg('blkif_be_create_t',
+                      { 'domid'        : self.controller.dom,
+                        'blkif_handle' : self.handle })
+        self.writeRequest(msg, response=d)
+        return d
+
+    def respond_be_create(self, msg):
+        val = unpackMsg('blkif_be_create_t', msg)
+        print 'respond_be_create>', val
+        self.connected = 1
+        return self
+    
+    def destroy(self):
+        """Disconnect from the blkif control interface and destroy it.
+        """
+        def cb_destroy(val):
+            self.send_be_destroy()
+        d = defer.Deferred()
+        d.addCallback(cb_destroy)
+        self.send_be_disconnect(response=d)
+        
+    def send_be_disconnect(self, response=None):
+        log.debug('>BlkifBackendController>send_be_disconnect> %s', str(self))
+        msg = packMsg('blkif_be_disconnect_t',
+                      { 'domid'        : self.controller.dom,
+                        'blkif_handle' : self.handle })
+        self.writeRequest(msg, response=response)
+
+    def send_be_destroy(self, response=None):
+        log.debug('>BlkifBackendController>send_be_destroy> %s', str(self))
+        msg = packMsg('blkif_be_destroy_t',
+                      { 'domid'        : self.controller.dom,
+                        'blkif_handle' : self.handle })
+        self.writeRequest(msg, response=response)
+
+    def connectInterface(self, val):
+        self.evtchn = channel.eventChannel(0, self.controller.dom)
+        log.debug("Connecting blkif to event channel %s ports=%d:%d",
+                  str(self), self.evtchn['port1'], self.evtchn['port2'])
+        msg = packMsg('blkif_be_connect_t',
+                      { 'domid'        : self.controller.dom,
+                        'blkif_handle' : self.handle,
+                        'evtchn'       : self.evtchn['port1'],
+                        'shmem_frame'  : val['shmem_frame'] })
+        d = defer.Deferred()
+        d.addCallback(self.respond_be_connect)
+        self.writeRequest(msg, response=d)
+
+    def respond_be_connect(self, msg):
+        """Response handler for a be_connect message.
+
+        @param msg: message
+        @type  msg: xu message
+        """
+        val = unpackMsg('blkif_be_connect_t', msg)
+        print 'respond_be_connect>', str(self), val
+        self.send_fe_interface_status_changed()
+            
+    def send_fe_interface_status_changed(self, response=None):
+        msg = packMsg('blkif_fe_interface_status_changed_t',
+                      { 'handle' : self.handle,
+                        'status' : BLKIF_INTERFACE_STATUS_CONNECTED,
+                        'evtchn' : self.evtchn['port2'] })
+        self.controller.writeRequest(msg, response=response)
+        
+class BlkifControllerFactory(controller.ControllerFactory):
     """Factory for creating block device interface controllers.
     """
 
     def __init__(self):
-        controller.SplitControllerFactory.__init__(self)
+        controller.ControllerFactory.__init__(self)
 
-    def createInstance(self, dom, recreate=0, backend=0):
+    def createInstance(self, dom, recreate=0):
         """Create a block device controller for a domain.
 
         @param dom: domain
         @type  dom: int
         @param recreate: if true it's a recreate (after xend restart)
         @type  recreate: bool
-        @return: deferred
-        @rtype: twisted.internet.defer.Deferred
+        @return: block device controller
+        @rtype: BlkifController
         """
         blkif = self.getInstanceByDom(dom)
-        if blkif:
-            d = defer.Deferred()
-            d.callback(blkif)
-        else:
-            blkif = BlkifController(self, dom, backend)
+        if blkif is None:
+            blkif = BlkifController(self, dom)
             self.addInstance(blkif)
-            d = blkif.connect(recreate=recreate)
-        return d
+        return blkif
 
     def getDomainDevices(self, dom):
         """Get the block devices for a domain.
@@ -86,15 +169,13 @@ class BlkifControllerFactory(controller.SplitControllerFactory):
         blkif = self.getInstanceByDom(dom)
         return (blkif and blkif.getDevice(vdev)) or None
 
-    def createBackendController(self, dom):
-        return BlkifBackendController(self, dom)
-
-class BlkDev(controller.Dev):
+class BlkDev(controller.SplitDev):
     """Info record for a block device.
     """
 
-    def __init__(self, ctrl, vdev, mode, segment):
-        controller.Dev.__init__(self,  segment['device'], ctrl)
+    def __init__(self, ctrl, config, vdev, mode, segment):
+        controller.SplitDev.__init__(self,  segment['device'], ctrl)
+        self.config = config
         self.dev = None
         self.uname = None
         self.vdev = vdev
@@ -102,9 +183,10 @@ class BlkDev(controller.Dev):
         self.device = segment['device']
         self.start_sector = segment['start_sector']
         self.nr_sectors = segment['nr_sectors']
-
-    def getBackendController(self):
-        return self.controller.backendController
+        try:
+            self.backendDomain = int(sxp.child_value(config, 'backend', '0'))
+        except:
+            raise XendError('invalid backend domain')
 
     def readonly(self):
         return 'w' not in self.mode
@@ -125,77 +207,77 @@ class BlkDev(controller.Dev):
         log.debug("Destroying vbd domain=%d vdev=%d", self.controller.dom, self.vdev)
         self.send_be_vbd_destroy()
 
-    def attach(self, d):
+    def attach(self):
         """Attach the device to its controller.
 
-        @param d: deferred to call with the device on success
         """
-        d1 = defer.Deferred()
-        d1.addCallback(self.respond_be_vbd_create, d)
-        d1.addErrback(d.errback)
-        self.send_be_vbd_create(response=d1)
+        backend = self.getBackend()
+        d1 = backend.connect()
+        d2 = defer.Deferred()
+        d2.addCallback(self.send_be_vbd_create)
+        d1.chainDeferred(d2)
+        return d2
         
-    def send_be_vbd_create(self, response=None):
+    def send_be_vbd_create(self, val):
+        d = defer.Deferred()
+        d.addCallback(self.respond_be_vbd_create)
+        backend = self.getBackend()
         msg = packMsg('blkif_be_vbd_create_t',
                       { 'domid'        : self.controller.dom,
-                        'blkif_handle' : self.controller.handle,
+                        'blkif_handle' : backend.handle,
                         'vdevice'      : self.vdev,
                         'readonly'     : self.readonly() })
-        self.getBackendController().writeRequest(msg, response=response)
+        backend.writeRequest(msg, response=d)
+        return d
         
-    def respond_be_vbd_create(self, msg, d):
+    def respond_be_vbd_create(self, msg):
         """Response handler for a be_vbd_create message.
         Tries to grow the vbd.
 
         @param msg: message
         @type  msg: xu message
-        @param d: deferred to call
-        @type  d: Deferred
         """
         val = unpackMsg('blkif_be_vbd_create_t', msg)
-        d1 = defer.Deferred()
-        d1.addCallback(self.respond_be_vbd_grow, d)
-        if d: d1.addErrback(d.errback)
-        self.send_be_vbd_grow(response=d1)
+        d = self.send_be_vbd_grow()
+        d.addCallback(self.respond_be_vbd_grow)
+        return d
     
-    def send_be_vbd_grow(self, response=None):
+    def send_be_vbd_grow(self):
+        d = defer.Deferred()
+        backend = self.getBackend()
         msg = packMsg('blkif_be_vbd_grow_t',
                       { 'domid'                : self.controller.dom,
-                        'blkif_handle'         : self.controller.handle,
+                        'blkif_handle'         : backend.handle,
                         'vdevice'              : self.vdev,
                         'extent.device'        : self.device,
                         'extent.sector_start'  : self.start_sector,
                         'extent.sector_length' : self.nr_sectors })
-        self.getBackendController().writeRequest(msg, response=response)
+        backend.writeRequest(msg, response=d)
+        return d
 
-    def respond_be_vbd_grow(self, msg, d):
+    def respond_be_vbd_grow(self, msg):
         """Response handler for a be_vbd_grow message.
 
         @param msg: message
         @type  msg: xu message
-        @param d: deferred to call
-        @type  d: Deferred or None
         """
         val = unpackMsg('blkif_be_vbd_grow_t', msg)
        status = val['status']
        if status != BLKIF_BE_STATUS_OKAY:
-            err = XendError("Adding extent to vbd failed: device %d, error %d"
+            raise XendError("Adding extent to vbd failed: device %d, error %d"
                             % (self.vdev, status))
-            #if(d):
-            #    d.errback(err)
-            raise err
-        if d:
-            d.callback(self)
+        return self
 
     def send_be_vbd_destroy(self, response=None):
         log.debug('>BlkDev>send_be_vbd_destroy> dom=%d vdev=%d',
                   self.controller.dom, self.vdev)
+        backend = self.getBackend()
         msg = packMsg('blkif_be_vbd_destroy_t',
                       { 'domid'                : self.controller.dom,
-                        'blkif_handle'         : self.controller.handle,
+                        'blkif_handle'         : backend.handle,
                         'vdevice'              : self.vdev })
         self.controller.delDevice(self.vdev)
-        self.getBackendController().writeRequest(msg, response=response)
+        backend.writeRequest(msg, response=response)
         
         
 class BlkifController(controller.SplitController):
@@ -203,12 +285,12 @@ class BlkifController(controller.SplitController):
     for a domain.
     """
     
-    def __init__(self, factory, dom, backend):
+    def __init__(self, factory, dom):
         """Create a block device controller.
         The controller must be connected using connect() before it can be used.
         Do not call directly - use createInstance() on the factory instead.
         """
-        controller.SplitController.__init__(self, factory, dom, backend)
+        controller.SplitController.__init__(self, factory, dom)
         self.devices = {}
         self.addMethod(CMSG_BLKIF_FE,
                        CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED,
@@ -216,25 +298,22 @@ class BlkifController(controller.SplitController):
         self.addMethod(CMSG_BLKIF_FE,
                        CMSG_BLKIF_FE_INTERFACE_CONNECT,
                        self.recv_fe_interface_connect)
-        self.handle = 0
-        self.evtchn = None
         self.registerChannel()
 
     def sxpr(self):
         val = ['blkif', ['dom', self.dom]]
-        if self.evtchn:
-            val.append(['evtchn',
-                        self.evtchn['port1'],
-                        self.evtchn['port2']])
         return val
 
+    def createBackend(self, dom, handle):
+        return BlkifBackendController(self, dom, handle)
+
     def getDevices(self):
         return self.devices.values()
 
     def getDevice(self, vdev):
         return self.devices.get(vdev)
 
-    def addDevice(self, vdev, mode, segment):
+    def addDevice(self, config, vdev, mode, segment):
         """Add a device to the device table.
 
         @param vdev:     device index
@@ -246,8 +325,9 @@ class BlkifController(controller.SplitController):
         @return: device
         @rtype:  BlkDev
         """
-        if vdev in self.devices: return None
-        dev = BlkDev(self, vdev, mode, segment)
+        if vdev in self.devices:
+            raise XendError('device exists: ' + str(vdev))
+        dev = BlkDev(self, config, vdev, mode, segment)
         self.devices[vdev] = dev
         return dev
 
@@ -255,7 +335,7 @@ class BlkifController(controller.SplitController):
         if vdev in self.devices:
             del self.devices[vdev]
 
-    def attachDevice(self, vdev, mode, segment, recreate=0):
+    def attachDevice(self, config, vdev, mode, segment, recreate=0):
         """Attach a device to the specified interface.
         On success the returned deferred will be called with the device.
 
@@ -270,13 +350,11 @@ class BlkifController(controller.SplitController):
         @return: deferred
         @rtype:  Deferred
         """
-        dev = self.addDevice(vdev, mode, segment)
-        if not dev: return -1
-        d = defer.Deferred()
+        dev = self.addDevice(config, vdev, mode, segment)
         if recreate:
-            d.callback(dev)
+            d = defer.succeed(dev)
         else:
-            dev.attach(d)
+            d = dev.attach()
         return d
 
     def destroy(self):
@@ -284,7 +362,7 @@ class BlkifController(controller.SplitController):
         """
         log.debug("Destroying blkif domain=%d", self.dom)
         self.destroyDevices()
-        self.disconnect()
+        self.destroyBackends()
 
     def destroyDevices(self):
         """Destroy all devices.
@@ -292,87 +370,28 @@ class BlkifController(controller.SplitController):
         for dev in self.getDevices():
             dev.destroy()
 
-    def connect(self, recreate=0):
-        """Connect the controller to the blkif control interface.
-
-        @param recreate: true if after xend restart
-        @return: deferred
-        """
-        log.debug("Connecting blkif domain=%d", self.dom)
-        d = defer.Deferred()
-        if recreate:
-            d.callback(self)
-        else:
-            def cbresp(msg):
-                return self
-            d.addCallback(cbresp)
-            self.send_be_create(response=d)
-        return d
-        
-    def send_be_create(self, response=None):
-        msg = packMsg('blkif_be_create_t',
-                      { 'domid'        : self.dom,
-                        'blkif_handle' : self.handle })
-        self.backendController.writeRequest(msg, response=response)
-    
-    def disconnect(self):
-        """Disconnect from the blkif control interface and destroy it.
-        """
-        def cb_destroy(val):
-            self.send_be_destroy()
-        d = defer.Deferred()
-        d.addCallback(cb_destroy)
-        self.send_be_disconnect(response=d)
-        
-    def send_be_disconnect(self, response=None):
-        log.debug('>BlkifController>send_be_disconnect> dom=%d', self.dom)
-        msg = packMsg('blkif_be_disconnect_t',
-                      { 'domid'        : self.dom,
-                        'blkif_handle' : self.handle })
-        self.backendController.writeRequest(msg, response=response)
+    def destroyBackends(self):
+        for backend in self.getBackends():
+            backend.destroy()
 
-    def send_be_destroy(self, response=None):
-        log.debug('>BlkifController>send_be_destroy> dom=%d', self.dom)
-        msg = packMsg('blkif_be_destroy_t',
-                      { 'domid'        : self.dom,
-                        'blkif_handle' : self.handle })
-        self.backendController.writeRequest(msg, response=response)
-        
     def recv_fe_driver_status_changed(self, msg, req):
+        val = unpackMsg('blkif_fe_driver_status_changed_t', msg)
+        print 'recv_fe_driver_status_changed>', val
+        # For each backend?
         msg = packMsg('blkif_fe_interface_status_changed_t',
-                      { 'handle' : self.handle,
+                      { 'handle' : 0,
                         'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED,
                         'evtchn' : 0 })
         self.writeRequest(msg)
 
     def recv_fe_interface_connect(self, msg, req):
         val = unpackMsg('blkif_fe_interface_connect_t', msg)
-        self.evtchn = channel.eventChannel(0, self.dom)
-        log.debug("Connecting blkif to event channel dom=%d ports=%d:%d",
-                  self.dom, self.evtchn['port1'], self.evtchn['port2'])
-        msg = packMsg('blkif_be_connect_t',
-                      { 'domid'        : self.dom,
-                        'blkif_handle' : val['handle'],
-                        'evtchn'       : self.evtchn['port1'],
-                        'shmem_frame'  : val['shmem_frame'] })
-        d = defer.Deferred()
-        d.addCallback(self.respond_be_connect)
-        self.backendController.writeRequest(msg, response=d)
-
-    def respond_be_connect(self, msg):
-        """Response handler for a be_connect message.
+        handle = val['handle']
+        backend = self.getBackendByHandle(handle)
+        if backend:
+            backend.connectInterface(val)
+        else:
+            log.error('interface connect on unknown interface: handle=%d', handle)
 
-        @param msg: message
-        @type  msg: xu message
-        """
-        val = unpackMsg('blkif_be_connect_t', msg)
-        self.send_fe_interface_status_changed()
-            
-    def send_fe_interface_status_changed(self, response=None):
-        msg = packMsg('blkif_fe_interface_status_changed_t',
-                      { 'handle' : self.handle,
-                        'status' : BLKIF_INTERFACE_STATUS_CONNECTED,
-                        'evtchn' : self.evtchn['port2'] })
-        self.writeRequest(msg, response=response)
     
 
index 28662207bbfe91f2d978a61e81ff747f7025b03b..dd1a9e6ebefad72665bdbf289026b4673db9945d 100755 (executable)
@@ -372,68 +372,11 @@ class Controller(CtrlMsgRcvr):
         self.deregisterChannel()
         self.factory.instanceClosed(self)
 
-class SplitControllerFactory(ControllerFactory):
-    """Factory for SplitControllers.
-    
-    @ivar backends:  mapping of domain id to backend
-    @type backends:  {int: BackendController}
-    """
-    
-    def __init__(self):
-        ControllerFactory.__init__(self)
-        self.backends = {}
-
-    def createInstance(self, dom, recreate=0, backend=0):
-        """Create an instance. Define in a subclass.
-
-        @param dom: domain
-        @type  dom: int
-        @param recreate: true if the instance is being recreated (after xend restart)
-        @type  recreate: int
-        @param backend: backend domain
-        @type  backend: int
-        @return: controller instance
-        @rtype:  SplitController (or subclass)
-        """
-        raise NotImplementedError()
-        
-    def getBackendController(self, dom):
-        """Get the backend controller for a domain.
-
-        @param dom: domain
-        @return: backend controller
-        """
-        ctrlr = self.backends.get(dom)
-        if ctrlr is None:
-            ctrlr = self.createBackendController(dom)
-            self.backends[dom] = ctrlr
-        return ctrlr
-
-    def createBackendController(self, dom):
-        """Create a backend controller. Define in a subclass.
-
-        @param dom: domain
-        """
-        raise NotImplementedError()
-
-    def delBackendController(self, ctrlr):
-        """Remove a backend controller.
-
-        @param ctrlr: backend controller
-        """
-        if ctrlr.dom in self.backends:
-            del self.backends[ctrlr.dom]
-
-    def backendControllerClosed(self, ctrlr):
-        """Callback called when a backend is closed.
-        """
-        self.delBackendController(ctrlr)
-
 class BackendController(CtrlMsgRcvr):
     """Abstract class for a backend device controller attached to a domain.
 
-    @ivar factory: controller factory
-    @type factory: ControllerFactory
+    @ivar controller: frontend controller
+    @type controller: Controller
     @ivar dom:     domain
     @type dom:     int
     @ivar channel: channel to the domain
@@ -441,10 +384,11 @@ class BackendController(CtrlMsgRcvr):
     """
 
     
-    def __init__(self, factory, dom):
+    def __init__(self, controller, dom, handle):
         CtrlMsgRcvr.__init__(self)
-        self.factory = factory
+        self.controller = controller
         self.dom = int(dom)
+        self.handle = handle
         self.channel = None
         
     def close(self):
@@ -452,31 +396,66 @@ class BackendController(CtrlMsgRcvr):
 
     def lostChannel(self):
         self.deregisterChannel()
-        self.factory.instanceClosed(self)
-
-
+        self.controller.backendClosed(self)
+        
 class SplitController(Controller):
     """Abstract class for a device controller attached to a domain.
-    A SplitController has a BackendContoller.
+    A SplitController manages a BackendController for each backend domain
+    it has at least one device for.
     """
 
-    def __init__(self, factory, dom, backend):
+    def __init__(self, factory, dom):
         Controller.__init__(self, factory, dom)
-        self.backendDomain = None
-        self.backendController = None
-        self.setBackendDomain(backend)
+        self.backends = {}
+        self.backendHandle = 0
         
-    def setBackendDomain(self, dom):
-        ctrlr = self.factory.getBackendController(dom)
-        self.backendDomain = ctrlr.dom
-        self.backendController = ctrlr
+    def getBackends(self):
+        return self.backends.values()
+
+    def getBackendByHandle(self, handle):
+        for b in self.getBackends():
+            if b.handle == handle:
+                return b
+        return None
+
+    def getBackendByDomain(self, dom):
+        return self.backends.get(dom)
+
+    def getBackend(self, dom):
+        """Get the backend controller for a domain.
+
+        @param dom: domain
+        @return: backend controller
+        """
+        b = self.getBackendByDomain(dom)
+        if b is None:
+            handle = self.backendHandle
+            self.backendHandle += 1
+            b = self.createBackend(dom, handle)
+            self.backends[b.dom] = b
+        return b
+
+    def createBackend(self, dom, handle):
+        """Create a backend controller. Define in a subclass.
+
+        @param dom: domain
+        @param handle: controller handle
+        """
+        raise NotImplementedError()
 
-    def getBackendDomain(self):
-        return self.backendDomain
+    def delBackend(self, ctrlr):
+        """Remove a backend controller.
 
-    def getBackendController(self):
-        return self.backendController
+        @param ctrlr: backend controller
+        """
+        if ctrlr.dom in self.backends:
+            del self.backends[ctrlr.dom]
 
+    def backendClosed(self, ctrlr):
+        """Callback called when a backend is closed.
+        """
+        self.delBackend(ctrlr)
+        
 class Dev:
     """Abstract class for a device attached to a device controller.
 
@@ -517,4 +496,15 @@ class Dev:
         """
         raise NotImplementedError()
 
+class SplitDev(Dev):
+
+    def __init__(self, idx, controller):
+        Dev.__init__(self, idx, controller)
+        self.backendDomain = 0
+
+    def getBackend(self):
+        return self.controller.getBackend(self.backendDomain)
+
+
+
     
index a5add8e7fb4ce931a02718d9630013b8a87040d8..864f6ebd2dfa8d42ef47d976d3c0db3d5ad98df2 100755 (executable)
@@ -22,8 +22,8 @@ class NetifBackendController(controller.BackendController):
     """Handler for the 'back-end' channel to a device driver domain.
     """
     
-    def __init__(self, factory, dom):
-        controller.BackendController.__init__(self, factory, dom)
+    def __init__(self, ctrl, dom, handle):
+        controller.BackendController.__init__(self, ctrl, dom, handle)
         self.addMethod(CMSG_NETIF_BE,
                        CMSG_NETIF_BE_DRIVER_STATUS_CHANGED,
                        self.recv_be_driver_status_changed)
@@ -33,14 +33,14 @@ class NetifBackendController(controller.BackendController):
         val = unpackMsg('netif_be_driver_status_changed_t', msg)
         status = val['status']
 
-class NetifControllerFactory(controller.SplitControllerFactory):
+class NetifControllerFactory(controller.ControllerFactory):
     """Factory for creating network interface controllers.
     """
 
     def __init__(self):
         controller.ControllerFactory.__init__(self)
 
-    def createInstance(self, dom, recreate=0, backend=0):
+    def createInstance(self, dom, recreate=0):
         """Create or find the network interface controller for a domain.
 
         @param dom:      domain
@@ -49,7 +49,7 @@ class NetifControllerFactory(controller.SplitControllerFactory):
         """
         netif = self.getInstanceByDom(dom)
         if netif is None:
-            netif = NetifController(self, dom, backend=backend)
+            netif = NetifController(self, dom)
             self.addInstance(netif)
         return netif
 
@@ -72,22 +72,16 @@ class NetifControllerFactory(controller.SplitControllerFactory):
         netif = self.getInstanceByDom(dom)
         return (netif and netif.getDevice(vif)) or None
         
-    def createBackendController(self, dom):
-        return NetifBackendController(self, dom)
-
-class NetDev(controller.Dev):
+class NetDev(controller.SplitDev):
     """Info record for a network device.
     """
 
     def __init__(self, ctrl, vif, config):
-        controller.Dev.__init__(self, vif, ctrl)
+        controller.SplitDev.__init__(self, vif, ctrl)
         self.vif = vif
         self.evtchn = None
         self.configure(config)
 
-    def getBackendController(self):
-        return self.controller.backendController
-
     def configure(self, config):
         self.config = config
         self.mac = None
@@ -108,6 +102,11 @@ class NetDev(controller.Dev):
         for ipaddr in ipaddrs:
             self.ipaddr.append(sxp.child0(ipaddr))
         
+        try:
+            self.backendDomain = int(sxp.child_value(config, 'backend', '0'))
+        except:
+            raise XendError('invalid backend domain')
+
     def sxpr(self):
         vif = str(self.vif)
         mac = self.get_mac()
@@ -168,16 +167,25 @@ class NetDev(controller.Dev):
         if vnet:
             vnet.vifctl(op, self.get_vifname(), self.get_mac())
 
-    def attach(self, d):
-        print 'attach>', d
-        self.send_be_create(response=d)
+    def attach(self):
+        print 'attach>'
+        d = self.send_be_create()
+        d.addCallback(self.respond_be_create)
+        return d
 
-    def send_be_create(self, response=None):
+    def send_be_create(self):
+        d = defer.Deferred()
         msg = packMsg('netif_be_create_t',
                       { 'domid'        : self.controller.dom,
                         'netif_handle' : self.vif,
                         'mac'          : self.mac })
-        self.getBackendController().writeRequest(msg, response=response)
+        self.getBackend().writeRequest(msg, response=d)
+        return d
+
+    def respond_be_create(self, msg):
+        val = unpackMsg('netif_be_create_t', msg)
+        print 'respond_be_create>', val
+        return self
 
     def destroy(self):
         """Destroy the device's resources and disconnect from the back-end
@@ -187,22 +195,23 @@ class NetDev(controller.Dev):
             self.send_be_destroy()
         log.debug("Destroying vif domain=%d vif=%d", self.controller.dom, self.vif)
         self.vifctl('down')
-        d = defer.Deferred()
+        d = self.send_be_disconnect()
         d.addCallback(cb_destroy)
-        self.send_be_disconnect(response=d)
 
-    def send_be_disconnect(self, response=None):
+    def send_be_disconnect(self):
+        d = defer.Deferred()
         msg = packMsg('netif_be_disconnect_t',
                       { 'domid'        : self.controller.dom,
                         'netif_handle' : self.vif })
-        self.getBackendController().writeRequest(msg, response=response)
+        self.getBackend().writeRequest(msg, response=d)
+        return d
 
     def send_be_destroy(self, response=None):
         msg = packMsg('netif_be_destroy_t',
                       { 'domid'        : self.controller.dom,
                         'netif_handle' : self.vif })
         self.controller.delDevice(self.vif)
-        self.getBackendController().writeRequest(msg, response=response)
+        self.getBackend().writeRequest(msg, response=response)
     
     def recv_fe_interface_connect(self, val, req):
         if not req: return
@@ -215,14 +224,12 @@ class NetDev(controller.Dev):
                         'rx_shmem_frame' : val['rx_shmem_frame'] })
         d = defer.Deferred()
         d.addCallback(self.respond_be_connect)
-        self.getBackendController().writeRequest(msg, response=d)
+        self.getBackend().writeRequest(msg, response=d)
         
     def respond_be_connect(self, msg):
         val = unpackMsg('netif_be_connect_t', msg)
         dom = val['domid']
         vif = val['netif_handle']
-        print 'respond_be_connect>', '     dom=', dom, '     vif=', vif
-        print 'respond_be_connect>', 'self.dom=', self.controller.dom, 'self.vif=', self.vif
         msg = packMsg('netif_fe_interface_status_changed_t',
                       { 'handle' : self.vif,
                         'status' : NETIF_INTERFACE_STATUS_CONNECTED,
@@ -242,8 +249,8 @@ class NetifController(controller.SplitController):
     """Network interface controller. Handles all network devices for a domain.
     """
     
-    def __init__(self, factory, dom, backend):
-        controller.SplitController.__init__(self, factory, dom, backend)
+    def __init__(self, factory, dom):
+        controller.SplitController.__init__(self, factory, dom)
         self.devices = {}
         self.addMethod(CMSG_NETIF_FE,
                        CMSG_NETIF_FE_DRIVER_STATUS_CHANGED,
@@ -253,6 +260,9 @@ class NetifController(controller.SplitController):
                        self.recv_fe_interface_connect)
         self.registerChannel()
 
+    def createBackend(self, dom, handle):
+        return NetifBackendController(self, dom, handle)
+
     def sxpr(self):
         val = ['netif', ['dom', self.dom]]
         return val
@@ -282,6 +292,8 @@ class NetifController(controller.SplitController):
         @param config: device configuration 
         @return: device
         """
+        if vif in self.devices:
+            raise XendError('device exists:' + str(vif))
         dev = NetDev(self, vif, config)
         self.devices[vif] = dev
         return dev
@@ -310,11 +322,10 @@ class NetifController(controller.SplitController):
         @return: deferred
         """
         dev = self.addDevice(vif, config)
-        d = defer.Deferred()
         if recreate:
-            d.callback(self)
+            d = defer.succeed(dev)
         else:
-            dev.attach(d)
+            d = dev.attach()
         return d
 
     def recv_fe_driver_status_changed(self, msg, req):
@@ -333,5 +344,6 @@ class NetifController(controller.SplitController):
         if dev:
             dev.recv_fe_interface_connect(val, req)
         else:
-            log.error('Received netif_fe_interface_connect for unknown vif: '+vif)
+            log.error('Received netif_fe_interface_connect for unknown vif: dom=%d vif=%d',
+                      self.dom, vif)
 
index 1a05da4e145057ea9cb3a7a44d958b448fad7649..d23bfcfd601da14930c479dc91257d5ea130c720 100644 (file)
@@ -126,19 +126,12 @@ gopts.var('netif', val='no|yes',
           fn=set_bool, default=0,
           use="Make the domain a network interface backend.")
 
-gopts.var('vbd_backend', val='DOM',
-          fn=set_value, default=None,
-          use='Set the domain to use for the vbd backend.')
-
-gopts.var('vif_backend', val='DOM',
-          fn=set_value, default=None,
-          use='Set the domain to use for the vif backend.')
-
-gopts.var('disk', val='phy:DEV,VDEV,MODE',
+gopts.var('disk', val='phy:DEV,VDEV,MODE[,DOM]',
           fn=append_value, default=[],
           use="""Add a disk device to a domain. The physical device is DEV,
          which is exported to the domain as VDEV. The disk is read-only if MODE
-         is 'r', read-write if MODE is 'w'.
+         is 'r', read-write if MODE is 'w'. If DOM is specified it defines the
+         backend driver domain to use for the disk.
          The option may be repeated to add more than one disk.
          """)
 
@@ -153,13 +146,14 @@ gopts.var('ipaddr', val="IPADDR",
           fn=append_value, default=[],
           use="Add an IP address to the domain.")
 
-gopts.var('vif', val="mac=MAC,bridge=BRIDGE,script=SCRIPT",
+gopts.var('vif', val="mac=MAC,bridge=BRIDGE,script=SCRIPT,backend=DOM",
           fn=append_value, default=[],
           use="""Add a network interface with the given MAC address and bridge.
          The vif is configured by calling the given configuration script.
          If mac is not specified a random MAC address is used.
          If bridge is not specified the default bridge is used.
          If script is not specified the default script is used.
+         If backend is not specified the default backend driver domain is used.
          This option may be repeated to add more than one vif.
          Specifying vifs will increase the number of interfaces as needed.
          """)
@@ -241,11 +235,13 @@ def configure_image(config, vals):
 def configure_disks(config_devs, vals):
     """Create the config for disks (virtual block devices).
     """
-    for (uname, dev, mode) in vals.disk:
+    for (uname, dev, mode, backend) in vals.disk:
         config_vbd = ['vbd',
                       ['uname', uname],
                       ['dev', dev ],
                       ['mode', mode ] ]
+        if backend:
+            config_vbd.append(['backend', backend])
         config_devs.append(['device', config_vbd])
 
 def configure_pci(config_devs, vals):
@@ -285,16 +281,20 @@ def configure_vifs(config_devs, vals):
             mac = d.get('mac')
             bridge = d.get('bridge')
             script = d.get('script')
+            backend = d.get('backend')
         else:
             mac = randomMAC()
             bridge = None
             script = None
+            backend = None
         config_vif = ['vif']
         config_vif.append(['mac', mac])
         if bridge:
             config_vif.append(['bridge', bridge])
         if script:
             config_vif.append(['script', script])
+        if backend:
+            config_vif.append(['backend', backend])
         config_devs.append(['device', config_vif])
 
 def configure_vfr(config, vals):
@@ -320,10 +320,6 @@ def make_config(vals):
         config.append(['backend', ['blkif']])
     if vals.netif:
         config.append(['backend', ['netif']])
-    if vals.vbd_backend:
-        config.append(['backend', ['vbd', ['dom', vals.vbd_backend]]])
-    if vals.vif_backend:
-        config.append(['backend', ['vif', ['dom', vals.vif_backend]]])
     if vals.restart:
         config.append(['restart', vals.restart])
     if vals.console:
@@ -342,7 +338,12 @@ def preprocess_disk(opts, vals):
     disk = []
     for v in vals.disk:
         d = v.split(',')
-        if len(d) != 3:
+        n = len(d)
+        if n == 3:
+            d.append(none)
+        elif n == 4:
+            pass
+        else:
             opts.err('Invalid disk specifier: ' + v)
         disk.append(d)
     vals.disk = disk
@@ -369,7 +370,7 @@ def preprocess_vifs(opts, vals):
             (k, v) = b.strip().split('=', 1)
             k = k.strip()
             v = v.strip()
-            if k not in ['mac', 'bridge']:
+            if k not in ['mac', 'bridge', 'script', 'backend']:
                 opts.err('Invalid vif specifier: ' + vif)
             d[k] = v
         vifs.append(d)